/************************* (C) COPYRIGHT 2011 J&DSoft **************************
* File Name          : SizeVariableTest.с
* Author             : Litvin Yuriy
* TS Idea            : 2011
* TS Version         : 2013-09-19 20:26:36
* Description        : Производит тестирование функций модуля "DataSizeVariable".
*******************************************************************************/
#include <time.h>
#include <limits.h>
#include <QtTest>
#include "SizeVariable.h"



class DataSizeVariableLocalTest : public QObject
{
    Q_OBJECT
    
public:
    DataSizeVariableLocalTest();
    
private Q_SLOTS:
    void test_Main();
    void test_Stream_SizeVariable_GetCountEffectiveBits();
    void test_Stream_SizeVariable_GetLength();
    void test_SizeT_SizeVariable_GetLength();
    void test_Stream_SizeVariable_isValidRange();
    void test_DSV_pData_SetAndGetSizeT();
};

DataSizeVariableLocalTest::DataSizeVariableLocalTest()
{
}

void DataSizeVariableLocalTest::test_Main()
{
    c8 mc8Data[10] = {0};
    c8 * const pStreamBegin = &mc8Data[0];
    const c8 * const pStreamEnd = &mc8Data[sizeof(mc8Data)];
    c8 * pStreamOut;
    const c8 * pStreamIn;

    qsrand(time(0));

    // Тестирование одного числа в потоке
    for( ui i = 0; i < 1000; i++ )
    {
        pStreamOut = pStreamBegin;
        size_t Size = (qrand() * qrand()) & 0xFFFFFFF;
        QVERIFY(DSV_Stream_SetSizeT( &pStreamOut, pStreamEnd, Size ));

        pStreamIn = pStreamBegin;
        size_t Temp = 0;
        QVERIFY(DSV_Stream_GetSizeT( &pStreamIn, pStreamEnd, &Temp ));

        QVERIFY(Size == Temp);
    }

    // Тестирование двух чисел в потоке
    for( ui i = 0; i < 1000; i++ )
    {
        pStreamOut = pStreamBegin;
        size_t Size1 = (qrand() * qrand()) & 0xFFFFFFF;
        QVERIFY(DSV_Stream_SetSizeT( &pStreamOut, pStreamEnd, Size1 ));
        size_t Size2 = (qrand() * qrand()) & 0xFFFFFFF;
        QVERIFY(DSV_Stream_SetSizeT( &pStreamOut, pStreamEnd, Size2 ));

        pStreamIn = pStreamBegin;
        size_t Temp1 = 0;
        QVERIFY(DSV_Stream_GetSizeT( &pStreamIn, pStreamEnd, &Temp1 ));
        size_t Temp2 = 0;
        QVERIFY(DSV_Stream_GetSizeT( &pStreamIn, pStreamEnd, &Temp2 ));

        QVERIFY(Size1 == Temp1 && Size2 == Temp2);
    }
}


void DataSizeVariableLocalTest::test_Stream_SizeVariable_GetCountEffectiveBits()
{
    c8 mc8Data[10] = {0};
    c8 * const pStreamBegin = &mc8Data[0];
    const c8 * const pStreamEnd = &mc8Data[sizeof(mc8Data)];
    c8 * pStream;

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)0);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 1));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)1);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 2));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)2);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 3));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)2);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x7F));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)7);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x0111));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)9);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x00010000));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)17);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x01000000));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)25);

    if (sizeof(size_t) == 4)
    {
        pStream = pStreamBegin;
        QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x0F100000));
        QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)28);

        pStream = pStreamBegin;
        QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x1F100000) == bFALSE);
    }

#if INT_MIN < LONG_MIN // x64, sizeof(size_t) == 8?
    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x0000100FFFFFFF00));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)45);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x0080000FFFFFFF00));
    QCOMPARE(DSV_Stream_GetCountEffectiveBits(pStreamBegin), (ui)56);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x0180000FFFFFFF00) == bFALSE);
#endif // #if INT_MIN < LONG_MIN
}


void DataSizeVariableLocalTest::test_Stream_SizeVariable_GetLength()
{
    c8 mc8Data[10] = {0};
    c8 * const pStreamBegin = &mc8Data[0];
    const c8 * const pStreamEnd = &mc8Data[sizeof(mc8Data)];
    c8 * pStream;

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0));
    QCOMPARE(DSV_Stream_GetLength(pStreamBegin), (ui)1);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x7F));
    QCOMPARE(DSV_Stream_GetLength(pStreamBegin), (ui)1);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x80));
    QCOMPARE(DSV_Stream_GetLength(pStreamBegin), (ui)2);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x0111));
    QCOMPARE(DSV_Stream_GetLength(pStreamBegin), (ui)2);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x4111));
    QCOMPARE(DSV_Stream_GetLength(pStreamBegin), (ui)3);
}


void DataSizeVariableLocalTest::test_SizeT_SizeVariable_GetLength()
{
    QCOMPARE(DSV_SizeT_GetLength(0), (ui)1);
    QCOMPARE(DSV_SizeT_GetLength(0x7F), (ui)1);
    QCOMPARE(DSV_SizeT_GetLength(0x80), (ui)2);
    QCOMPARE(DSV_SizeT_GetLength(0x0111), (ui)2);
    QCOMPARE(DSV_SizeT_GetLength(0x4111), (ui)3);
}


void DataSizeVariableLocalTest::test_Stream_SizeVariable_isValidRange()
{
    c8 mc8Data[10] = {0};
    c8 * const pStreamBegin = &mc8Data[0];
    const c8 * const pStreamEnd = &mc8Data[sizeof(mc8Data)];
    c8 * pStream;

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0));
    QVERIFY(DSV_Stream_ObjectInRange(pStreamBegin, pStreamBegin) == bFALSE);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0));
    QVERIFY(DSV_Stream_ObjectInRange(pStreamBegin, pStreamBegin + 1));

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x01000000));
    QVERIFY(DSV_Stream_ObjectInRange(pStreamBegin, pStreamBegin + 3) == bFALSE);

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x01000000));
    QVERIFY(DSV_Stream_ObjectInRange(pStreamBegin, pStreamBegin + 4));

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x08000000));
    QVERIFY(DSV_Stream_ObjectInRange(pStreamBegin, pStreamBegin + 4));

    pStream = pStreamBegin;
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x10000000-1));
    QVERIFY(DSV_Stream_SetSizeT(&pStream, pStreamEnd, 0x10000000) == bFALSE);
}


void DataSizeVariableLocalTest::test_DSV_pData_SetAndGetSizeT()
{
    c8 mc8Data[sizeof(size_t)] = {0};

    size_t Readed;
    if (sizeof(size_t) >= 4)
    {
        bool r = true;
        for (size_t i = 0; i < ((size_t)1 << 28);)
        {
            r = DSV_pData_SetSizeT(mc8Data, i);
            if (!r)
            {
                QVERIFY(r);
            }
            r = DSV_pData_GetSizeT(mc8Data, &Readed);
            if (!r)
            {
                QVERIFY(r);
            }
            if (Readed != i)
            {
                QCOMPARE(Readed, i);
            }
            i += 1 + (i >> 8);
        }

        QVERIFY(DSV_pData_SetSizeT(mc8Data, (size_t)0x7777777));
    }

    if (sizeof(size_t) == 4)
    {
        QCOMPARE(DSV_pData_SetSizeT(mc8Data, ((size_t)1 << 28)), 0u);
        QCOMPARE(DSV_pData_SetSizeT(mc8Data, ((size_t)1 << 28) + 500), 0u);
    }

#if INT_MIN < LONG_MIN // x64, sizeof(size_t) == 8?
    {
        bool r = true;
        for (size_t i = 0; i < (1ull << 56);)
        {
            if (DSV_SizeT_GetLength(i) > 4)
            {
                r = true;
            }

            r = DSV_pData_SetSizeT(mc8Data, i);
            if (!r)
            {
                QVERIFY(r);
            }
            r = DSV_pData_GetSizeT(mc8Data, &Readed);
            if (!r)
            {
                QVERIFY(r);
            }
            if (Readed != i)
            {
                QCOMPARE(Readed, i);
            }
            i += 1 + (i >> 8);
        }

        QCOMPARE(DSV_pData_SetSizeT(mc8Data, ((size_t)1 << 56)), 0u);
        QCOMPARE(DSV_pData_SetSizeT(mc8Data, ((size_t)1 << 56) + 500), 0u);
    }
#endif // #if INT_MIN < LONG_MIN
}

QTEST_APPLESS_MAIN(DataSizeVariableLocalTest)

#include "tst_datasizevariablelocaltest.moc"
